package com.example.dubbo.storage.core.utils;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.Calendar;
import java.util.Date;

public class JodaTimeUtil {

    public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String MILLS_NUMBER_FORMAT = "yyyyMMddHHmmssSSS";
    public static final String MILLS_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DAY_FORMAT = "yyyy-MM-dd";
    public static final String MONTH_FORMAT = "yyyy-MM";
    public static final String HOUR_MINUTE_FORMAT = "HH:mm";
    public static final String DATE_HOUR_MINUTE_FORMAT = "yyyy-MM-dd HH:mm";

    public static String format(Date date) {
        DateTime dateTime = new DateTime(date);
        return dateTime.toString(STANDARD_FORMAT);
    }

    public static String format(Date date, String format) {
        DateTime dateTime = new DateTime(date);
        return dateTime.toString(format);
    }

    public static Date parseDate(String dateTimeStr) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(STANDARD_FORMAT);
        DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
        return dateTime.toDate();
    }

    public static Date parseDate(String dateTimeStr, String format) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(format);
        DateTime dateTime = dateTimeFormatter.parseDateTime(dateTimeStr);
        return dateTime.toDate();
    }

    public static Date getBeginTimeOfDay(Date date) {
        DateTime dateTime = new DateTime(date);
        return dateTime.withTimeAtStartOfDay().toDate();
    }

    public static Date getEndTimeOfDay(Date date) {
        DateTime dateTime = new DateTime(date);
        return dateTime.millisOfDay().withMaximumValue().toDate();
    }

    // 获取本周周日23:59:59点，按周一为每周第一天
    public static Date getEndTimeOfSunday(Date date) {
        Date beginTimeOfMonday = getBeginTimeOfMonday(date);
        Date addWeek = addWeek(beginTimeOfMonday, 1);
        return new Date(addWeek.getTime() - 1);
    }

    // 获取本周周一0点，按周一为每周第一天
    public static Date getBeginTimeOfMonday(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        // 如果是周日
        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
            calendar.add(Calendar.DAY_OF_YEAR, -1);
        }
        // 获取当前日期是当周的第i天
        int i = calendar.get(Calendar.DAY_OF_WEEK) - 1;

        // 获取当前日期所在周的第一天
        calendar.add(Calendar.DATE, -i + 1);

        return getBeginTimeOfDay(calendar.getTime());
    }

    public static int getDayOfWeek(Date date) {
        DateTime dateTime = new DateTime(date);
        return dateTime.getDayOfWeek();
    }

    public static Date getBeginTimeOfMonth(Date date) {
        DateTime dateTime = new DateTime(date);
        Date beginDateOfMonth = dateTime.dayOfMonth().withMinimumValue().toDate();
        return getBeginTimeOfDay(beginDateOfMonth);
    }

    public static Date getEndTimeOfMonth(Date date) {
        DateTime dateTime = new DateTime(date);
        Date endDateOfMonth = dateTime.dayOfMonth().withMaximumValue().toDate();
        return getEndTimeOfDay(endDateOfMonth);
    }

    public static Date getBeginTimeOfWeek(Date date) {
        DateTime dateTime = new DateTime(date);
        Date beginDateOfMonth = dateTime.dayOfWeek().withMinimumValue().toDate();
        return getBeginTimeOfDay(beginDateOfMonth);
    }

    public static Date getEndTimeOfWeek(Date date) {
        DateTime dateTime = new DateTime(date);
        Date endDateOfMonth = dateTime.dayOfWeek().withMaximumValue().toDate();
        return getEndTimeOfDay(endDateOfMonth);
    }

    public static Date getBeginTimeOfYear(Date date) {
        DateTime dateTime = new DateTime(date);
        Date beginDateOfMonth = dateTime.dayOfYear().withMinimumValue().toDate();
        return getBeginTimeOfDay(beginDateOfMonth);
    }

    public static Date getEndTimeOfYear(Date date) {
        DateTime dateTime = new DateTime(date);
        Date endDateOfMonth = dateTime.dayOfYear().withMaximumValue().toDate();
        return getEndTimeOfDay(endDateOfMonth);
    }

    public static Date addYear(Date date, int year) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusYears(year).toDate();
    }

    public static Date addMonth(Date date, int month) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMonths(month).toDate();
    }

    public static Date addDay(Date date, int day) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusDays(day).toDate();
    }

    public static Date addWeek(Date date, int week) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusWeeks(week).toDate();
    }

    public static Date addHour(Date date, int hour) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusHours(hour).toDate();
    }

    public static Date addMinute(Date date, int minute) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMinutes(minute).toDate();
    }

    public static Date addSecond(Date date, int second) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusSeconds(second).toDate();
    }

    public static void main(String[] args) {
        System.out.println(JodaTimeUtil.format(new Date()));
        System.out.println(JodaTimeUtil.parseDate("2023-03-11 11:34:04"));
        System.out.println(JodaTimeUtil.parseDate("2023-03-11", DAY_FORMAT));

        Date beginTimeOfDay = JodaTimeUtil.getBeginTimeOfDay(new Date());
        System.out.printf("beginTimeOfDay: %s \n", new DateTime(beginTimeOfDay).toString(MILLS_FORMAT));

        Date endTimeOfDay = JodaTimeUtil.getEndTimeOfDay(new Date());
        System.out.printf("endTimeOfDay: %s \n", new DateTime(endTimeOfDay).toString(MILLS_FORMAT));

        DateTime dateTime2 = new DateTime(2020, 2, 1, 10, 13, 14);
        System.out.printf("dateTime2: %s \n", dateTime2.toString(MILLS_FORMAT));

        Date date = addYear(new Date(), 2);
        System.out.println(JodaTimeUtil.format(date));
        date = addYear(new Date(), -4);
        System.out.println(JodaTimeUtil.format(date));
        date = addMonth(new Date(), 2);
        System.out.println(JodaTimeUtil.format(date));
        date = addDay(new Date(), 3);
        System.out.println(JodaTimeUtil.format(date));

        System.out.println(format(getBeginTimeOfMonday(new Date())));
        System.out.println(format(getEndTimeOfSunday(new Date())));

        System.out.println(format(getBeginTimeOfMonday(new Date())));
        System.out.println(format(getBeginTimeOfWeek(new Date())));
    }
}
